package com.fanketly.musicdiary.domain

import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.fanketly.musicdiary.data.model.DiaryModel
import com.fanketly.musicdiary.data.model.newDiaryModel
import com.fanketly.musicdiary.data.repository.DiaryRepo
import com.fanketly.musicdiary.domain.DiaryUiState.Success
import com.fanketly.musicdiary.domain.DiaryUiState.UnKnown
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import java.time.LocalDate
import javax.inject.Inject

@HiltViewModel
class DiaryViewModel @Inject constructor(private val repo: DiaryRepo) : ViewModel() {
    /**
     *used to notify the latest date
     **/
    private val _date by lazy {
        mutableStateOf(LocalDate.now())
    }
    val date: LocalDate
        get() = _date.value

    /**
     *get latest date
     **/
    fun updateDate() {
        LocalDate.now().let {
            if (_date.value.dayOfMonth != it.dayOfMonth) _date.value = it
        }
    }

    /**
     *数据库内容改变时会重新发送，而热流则会一直收集内容，经过map处理后通知订阅的ui
     **/
    val uiState: StateFlow<DiaryUiState> = getDiary().map {
        diaryList = it
        Success(it)
    }.stateIn(//stateIn converts data flow to StateFlow
        scope = viewModelScope,
        //configures a delay (in milliseconds) between the disappearance of the last subscriber and the stopping of the sharing coroutine. It defaults to zero (stop immediately).
        started = SharingStarted.WhileSubscribed(5000),
        initialValue = UnKnown
    )


    private val _diaryDetailData = mutableStateOf<DiaryModel?>(null)
    val diaryDetailData
        get() = _diaryDetailData.value
    private val _showDiaryDetail = mutableStateOf(false)
    val isShowDiaryDetail
        get() = _showDiaryDetail.value
    private lateinit var diaryList: List<DiaryModel>

    /**
     *此举是为了方便在viewModel里重复使用list
     **/
    fun getDiaries(): List<DiaryModel> {
        return diaryList
    }

    fun showToadyDiaryDetail() {
        updateDate()
        val nowDate = date
        showDiaryListDetail(diaryList.find { a -> a.year == nowDate.year && a.month == nowDate.monthValue && a.dayOfMonth == nowDate.dayOfMonth }
            ?: newDiaryModel(nowDate))
    }

    fun showDiaryListDetail(diaryModel: DiaryModel) {
        _diaryDetailData.value = diaryModel
        _showDiaryDetail.value = true
    }

    fun dismissDiaryDetail() {
        _showDiaryDetail.value = false
    }

    /**
     *get All Diary Data
     **/
    private fun getDiary() = repo.getAll()

    /**
     *update if insert fails
     **/
    fun update(diaryModel: DiaryModel) {
        viewModelScope.launch {
            _diaryDetailData.value = diaryModel
            repo.update(diaryModel)
        }
    }


    fun checkToadyDiary(): Boolean {
        return date.let {
            diaryList.find { a -> a.year == it.year && a.month == it.monthValue && a.dayOfMonth == it.dayOfMonth } != null
        }
    }


}